#include "ttMsgMap.h"
#include "ttCalcObjMgr.h"

ttMsgMap::_msgloopvar::_msgloopvar() : m_cx(0), 
m_cy(0), m_bBuilding(false), m_bLinking(false), 
m_bDragging(false), m_bBuildingAnd(false), 
m_bDeleting(false), m_bSetVal(false), m_bBuildingOr(false),
m_bBuildingNot(false), m_linkcnt(0)
{
	m_hPenBlue = CreatePen(PS_SOLID, 10, RGB(28, 227, 177));
	m_hPenRed = CreatePen(PS_SOLID, 10, RGB(255, 100, 100));
	m_hPenFlash = CreatePen(PS_SOLID, 2, RGB(28, 227, 177));
}

int
ttMsgMap::_msgloopvar::flagfalse()
{
	m_bBuilding = false;
	m_bLinking = false;
	m_bDragging = false;
	m_bDrawDragRect = false;
	m_bDragBegin = false;
	m_bBuildingAnd = false;
	m_bDeleting = false;
	m_bSetVal = false;
	m_bBuildingOr = false;
	m_bBuildingNot = false;
	m_lastDragX = -1;
	m_lastDragY = -1;
	m_InitDragRectX = -1;
	m_InitDragRectY = -1;
	m_crntDragRectX = -1;
	m_crntDragRectY = -1;
	m_linkcnt = 0;
	return 0;
}

int
ttMsgMap::_msgloopvar::drawLink(HDC hdc, ttPoint *begin, ttPoint *end)
{
	HPEN hOldPen = (HPEN)SelectObject(hdc, ttMsgMap::Get()->m_msglpvar.m_hPenBlue);
	MoveToEx(hdc, begin->getX(), begin->getY(), NULL);
	int mid_x = (end->getX() - begin->getX())/2 + begin->getX();
	int mid_y = (end->getY() - begin->getY())/2 + begin->getY();
	LineTo(hdc, mid_x, mid_y);
	SelectObject(hdc, ttMsgMap::Get()->m_msglpvar.m_hPenRed);
	LineTo(hdc, end->getX(), end->getY());
	SelectObject(hdc, hOldPen);
	return 0;
}

int
ttMsgMap::_msgloopvar::readAndInit()
{
	FILE *fp = fopen("in.txt", "r");
	if (NULL != fp){
		int len = 0;
		fscanf(fp, "%d", &len);
		for (int i = 0; i < len; ++ i){
			int num, x, y;
			fscanf(fp, "%d %d %d", &num, &x, &y);
			ttPoint *pttp = NULL;
			switch (num){
				case 0:
					pttp = new ttPoint;
					break;
				case 1:
					pttp = new notPoint;
					break;
				case 2:
					pttp = new andPoint;
					break;
				case 3:
					pttp = new orPoint;
					break;
			}
			pttp->setXY(x, y);
			ttCalcObjMgr::Get()->push(pttp);
		}

		fscanf(fp, "%d", &len);
		for (int i = 0; i < len; ++ i){
			int begin, end;
			fscanf(fp, "%d %d", &begin, &end);
			ttPoint *p1 = NULL, *p2 = NULL;
			p1 = (ttPoint*)ttCalcObjMgr::Get()->getObj(begin);
			p2 = (ttPoint*)ttCalcObjMgr::Get()->getObj(end);
			p1->link(p2);
			p2->linked(p1);
		}
		fclose(fp);
	}
	return 0;
}

int
ttMsgMap::_msgloopvar::writeAndUnint()
{
	FILE *fp = fopen("out.txt", "w");
	if (NULL != fp){
		int len = ttCalcObjMgr::Get()->length(), cnt = 0;
		fprintf(fp, "%d\n", len);
		for (int i = 0; i < len; ++ i){
			int num, x, y;
			IttCalcObj *pIttp = ttCalcObjMgr::Get()->getObj(i);
			switch(pIttp->getType()){
				case IttCalcObj::CO_POINT:
					num = 0;
					break;
				case IttCalcObj::CO_NOT:
					num = 1;
					break;
				case IttCalcObj::CO_AND:
					num = 2;
					break;
				case IttCalcObj::CO_OR:
					num = 3;
					break;
				default:
					return -1; // not valid type
			}
			ttPoint* pttp = (ttPoint*)pIttp;
			x = pttp->getX();
			y = pttp->getY();
			fprintf(fp, "%d %d %d\n", num, x, y);
			cnt += pttp->getOutputLength();
		}
		fprintf(fp, "%d\n", cnt);
		for (int i = 0; i < len; ++ i){
			IttCalcObj *pIttp = ttCalcObjMgr::Get()->getObj(i);
			switch(pIttp->getType()){
				case IttCalcObj::CO_POINT:
				case IttCalcObj::CO_NOT:
				case IttCalcObj::CO_AND:
				case IttCalcObj::CO_OR:
					break;
				default:
					return -1; // not valid type
			}
			ttPoint* pttp = (ttPoint*)pIttp;
			int outlen = pttp->getOutputLength();
			int begin = i;
			for (int j = 0; j < outlen; ++ j){ 
				int end = ttCalcObjMgr::Get()->indexOf(pttp->getOutput(j));
				fprintf(fp, "%d %d\n", begin, end);
			}
		}
		fclose(fp);
	}
}

int
ttMsgMap::_msgloopvar::drawDragRect(HDC hdc)
{
	if (-1 == this->m_InitDragRectX || -1 == this->m_crntDragRectX){
		return -1;
	}
	HPEN hOldPen = (HPEN)SelectObject(hdc, ttMsgMap::Get()->m_msglpvar.m_hPenBlue);
	HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, (HBRUSH)GetStockObject(NULL_BRUSH));
	Rectangle(hdc, this->m_InitDragRectX, this->m_InitDragRectY, this->m_crntDragRectX, this->m_crntDragRectY);
	SelectObject(hdc, hOldPen);
	return 0;
}

bool
ttMsgMap::_msgloopvar::inRect(int x, int y)
{
	return x >= this->m_InitDragRectX && x <= this->m_crntDragRectX &&
		y >= this->m_InitDragRectY && y <= this->m_crntDragRectY;
}

ttMsgMap::ttMsgMap() : m_defFunc(NULL)
{}

ttMsgMap::~ttMsgMap()
{
	for (TTLIST::iterator iter = m_MsgMap.begin(); iter != m_MsgMap.end(); ++ iter){
		if (NULL != (*iter)){
			delete *iter;
		}
	}
}

int 
ttMsgMap::push_front(IttFunc *pFunc)
{
	m_MsgMap.push_front(pFunc);
	return 0;
}

int 
ttMsgMap::run(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	for (TTLIST::iterator iter = m_MsgMap.begin(); iter != m_MsgMap.end(); ++ iter){
		if (NULL != (*iter)){
			int ret = (*iter)->runShell(hwnd, message, wParam, lParam);
			if (0 == ret){
				return ret;			
			}
			else if (1 == ret){
				return callDefFunc(hwnd, message, wParam, lParam);
			}
		}
	}
	return callDefFunc(hwnd, message, wParam, lParam);
}

int 
ttMsgMap::setDefFunc(IttFunc *pdef)
{
	m_defFunc = pdef;
	return 0;
}

int 
ttMsgMap::callDefFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (NULL != this->m_defFunc){
		return this->m_defFunc->runShell(hwnd, message, wParam, lParam);
	}
	return 0;
}

int
ttMsgMap::swaptosmall(int &x, int &y)
{
	if (x > y){
		int tmp = x;
		tmp = y;
		y = tmp;
	}
	return 0;
}